package my.framework.ssm.sample.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Objects;

/**
 * @author NuKi
 * @date 2018/11/21 19:58
 */
@Configuration
@Import({RedisConfig.class})
@PropertySource("classpath:config.properties")
@ComponentScan(basePackages = {"my.framework.ssm.sample.service",
        "my.framework.ssm.sample.common.advice"})
@MapperScan("my.framework.ssm.sample.mapper")
public class AppConfig {

    private final Environment env;

    public AppConfig(Environment env) {
        this.env = env;
    }

    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(env.getProperty("datasource.jdbc.url"));
        dataSource.setUsername(env.getProperty("datasource.jdbc.username"));
        dataSource.setPassword(env.getProperty("datasource.jdbc.password"));

        //配置监控统计拦截的filters
        dataSource.setFilters("mergeStat,wall,log4j2");
        //配置初始化大小、最小、最大
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(10);
        dataSource.setMaxActive(100);
        //配置获取连接等待超时的时间
        dataSource.setMaxWait(60000);
        dataSource.setValidationQuery("SELECT 'x'");
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setTestWhileIdle(true);
        //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
        dataSource.setTimeBetweenEvictionRunsMillis(60000);
        dataSource.setMinEvictableIdleTimeMillis(300000);
        //打开PSCache，并且指定每个连接上PSCache的大小
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

        dataSource.setRemoveAbandoned(false);
        dataSource.setRemoveAbandonedTimeout(180);
        dataSource.setLogAbandoned(true);
        return dataSource;
    }

    @Bean
    public MybatisSqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        //sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().
        //       getResources(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "mapper/**/*.xml"));
        sqlSessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setBanner(false);
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        dbConfig.setIdType(IdType.AUTO);
        dbConfig.setTableUnderline(true);
        globalConfig.setDbConfig(dbConfig);
        sqlSessionFactory.setGlobalConfig(globalConfig);

        PaginationInterceptor pagePlugin = new PaginationInterceptor();
        pagePlugin.setDialectType("mysql");
        sqlSessionFactory.setPlugins(new Interceptor[]{pagePlugin});

        return sqlSessionFactory;
    }

    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public EhCacheCacheManager ehCacheManager() {
        EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
        factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        factoryBean.setShared(true);
        factoryBean.afterPropertiesSet();
        return new EhCacheCacheManager(Objects.requireNonNull(factoryBean.getObject()));
    }
}
